/*
 * Copyright (C) 2015-2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "PlanetWars2dRT-SDL2/specific/compilation_config.h"
#include "PlanetWars2dRT-SDL2/utils/SDL.h"
#include "PlanetWars2dRT-SDL2/specific/view/draw_game.h"
#include "PlanetWars2dRT-core/specific/controller/game_playing.h"
#include "PlanetWars2dRT-SDL2/specific/controller/game_playing_data.h"
#include "PlanetWars2dRT-SDL2/specific/controller/game_playing.h"
#include "PlanetWars2dRT-core/specific/controller/player_robots.h"
#include "PlanetWars2dRT-core/specific/controller/planet_observer.h"
#include "PlanetWars2dRT-core/specific/model/universes.h"
#include "PlanetWars2dRT-core/utils/color_rgb_const.h"
#include "SDL_image.h"
#include <stdio.h>
#include <time.h>


void
add_players_to_game(struct game_t* a_game)
{
  struct player_t a_player;
  player_init_first_time_only(&a_player);
  
  if(!player_set_name(&a_player, "Human"))
    {
      fprintf(stderr, "Fail to define a name to a player!\n");
    }
  a_player.color  = COLOR_RGB_BLUE;
  a_player.act = NULL;
  if(!game_add_player(a_game, &a_player))
    {
      fprintf(stderr,
	      "Player '%s' not added!\n",
	      a_player.name);
    }
  
  if(!player_set_name(&a_player, "Robot 1"))
    {
      fprintf(stderr, "Fail to define a name to a player!\n");
    }
  a_player.color = COLOR_RGB_RED;
  a_player.act = player_robot_very_lazy_stupid_rusher_act;
  if(!game_add_player(a_game, &a_player))
    {
      fprintf(stderr,
	      "Player '%s' not added!\n",
	      a_player.name);
    }
  
  if(!player_set_name(&a_player, "Robot 2"))
    {
      fprintf(stderr, "Fail to define a name to a player!\n");
    }
  a_player.color = COLOR_RGB_ORANGE;
  a_player.act = player_robot_lazy_stupid_rusher_act;
  if(!game_add_player(a_game, &a_player))
    {
      fprintf(stderr,
	      "Player '%s' not added!\n",
	      a_player.name);
    }
  
  if(!player_set_name(&a_player, "Robot 3"))
    {
      fprintf(stderr, "Fail to define a name to a player!\n");
    }
  a_player.color = COLOR_RGB_VIOLET;
  a_player.act = player_robot_lazy_easy;
  if(!game_add_player(a_game, &a_player))
    {
      fprintf(stderr,
	      "Player '%s' not added!\n",
	      a_player.name);
    }
  
  if(!player_set_name(&a_player, "Robot 4"))
    {
      fprintf(stderr, "Fail to define a name to a player!\n");
    }
  a_player.color = COLOR_RGB_YELLOW;
  a_player.act = player_robot_lazy_normal;
  if(!game_add_player(a_game, &a_player))
    {
      fprintf(stderr,
	      "Player '%s' not added!\n",
	      a_player.name);
    }
}

bool
set_random_universe_to_game(game_t* a_game)
{
  size_2d_uint size;
  size.x = 700;
  size.y = 550;
  
  unsigned char nb_players = game_get_nb_players(a_game);
  a_game->universe = universe_generate_very_simple(size,
						nb_players * 3);
  universe_give_neutral_planet_to_true_players(&a_game->universe, nb_players);
  return true;
}

bool
set_default_hard_coded_universe_to_game(game_t* a_game)
{
  bool success;
  a_game->universe = get_universe_hard_coded_square_filled_small_9_planets(&success);
  return success;
}

struct game_t
create_game(bool put_ship_created_dispatcher)
{
  struct game_t a_game;
  game_init_first_time_only_default(&a_game);
  add_players_to_game(&a_game);
  
  if(!set_random_universe_to_game(&a_game))
    {
      fprintf(stderr,
	      "The universe is not complete!\n");
    }
  
  if(put_ship_created_dispatcher)
    {
      observer_t ship_dispatcher = planet_observer_new_ship_default_dispatcher_create();
      if(!universe_add_observer_to_planets(&a_game.universe,
					   &ship_dispatcher,
					   false))
	{
	  fprintf(stderr,
		  "Fail to add ship dispatcher on all planets!\n");
	}
    }

  return a_game;
}

bool
game_playing_with_SDL2(game_playing_t* game_playing,
		       SDL_Renderer*   main_window_renderer)
{
  if(!game_playing_run(game_playing))
    {
      return false;
    }
  
  if(!game_state_has_to_quit(&game_playing->state))
    {
      if(!SDL_draw_vector_game_end(main_window_renderer,
				   &game_playing->game,
				   stderr))
	{
	  return false;
	}
      SDL_RenderPresent(main_window_renderer);
      SDL_Delay(3000);
    }
  
  return true;
}


int
main(/*int argc, char* argv[]*/)
{
  srand(time(NULL));
  
  /* SDL2 and main window init */
  
  SDL_Window* main_window;
  main_window = SDL_and_main_window_init();
  if(main_window == NULL)
    {
      SDL_Quit();
      return EXIT_FAILURE;
    }
  
  const int IMG_INIT_FLAGS = IMG_INIT_PNG;
  if((IMG_Init(IMG_INIT_FLAGS) & IMG_INIT_FLAGS) != IMG_INIT_FLAGS)
    {
      fprintf(stderr, "IMG_Init: Failed to init required png support!\n");
    }
  SDL_Surface* icon = IMG_Load("etc/icon.png");
  if(icon == NULL)
    {
      fprintf(stderr, "Icon not loaded!\n");
    }
  else
    {
      SDL_SetWindowIcon(main_window, icon);
      SDL_FreeSurface(icon);
    }
  IMG_Quit();
  
  SDL_Renderer* main_window_renderer;
  main_window_renderer = SDL_CreateRenderer(main_window, -1,
					    SDL_RENDERER_ACCELERATED);
  if(main_window_renderer == NULL)
    {
      fprintf(stderr, "Renderer could not be created!\n");
      SDL_print_error();
      SDL_and_main_window_quit(main_window);
      return EXIT_FAILURE;
    }
  
  /* Playing the game */
  
  game_playing_t game_playing;
  game_playing.game = create_game(true);
  game_state_init_first_time_only(&game_playing.state);
  
  game_playing_data_sdl game_playing_data;
  game_playing_data_sdl_init_first_time_only(&game_playing_data);
  game_playing_data.main_window          = main_window;
  game_playing_data.main_window_renderer = main_window_renderer;
  game_playing.data = &game_playing_data;
  game_playing.data_free = NULL;
  game_playing.do_if_not_paused = game_playing_sdl_do_if_not_paused;
  game_playing.do_always        = game_playing_sdl_do_always;
  
  if(!game_playing_with_SDL2(&game_playing, main_window_renderer))
    {
      SDL_DestroyRenderer(main_window_renderer);
      SDL_and_main_window_quit(main_window);
      game_playing_destructor(&game_playing);
      return EXIT_FAILURE;
    }
  
  SDL_DestroyRenderer(main_window_renderer);
  SDL_and_main_window_quit(main_window);
  game_playing_destructor(&game_playing);
  return EXIT_SUCCESS;
}
